
/**
 * @file    bt_lcd.c
 * @author  chenwenrui
 * @brief   2位数码管显示
 * @version V1.0
 * @date 2023-12-21
 * @copyright Copyright (c) 2022
 *
 * 系统资源：
 *      GPIO:
 *          SPI_CLK P35
 *          SPI_STB P13
 *          SPI_DIO P14
 *          Backlight P36
 *
 */

#include "GPIO.h"
#include "bt_lcd.h"

/********************定义数据*************************/
static const unsigned char code Upright[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; // 0~F字型码
static const unsigned char code ZERO[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};    // 清屏
static const unsigned char code Reserve[16] = {0x3F, 0x30, 0x5B, 0x79, 0x74, 0x6d, 0x6F, 0x38, 0x7f, 0x7D, 0xfe, 0x77, 0x0f, 0xf3, 0x4f, 0x4E}; // 倒着显示的字型码

#define nop  \
    _nop_(); \
    _nop_(); \
    _nop_(); \
    _nop_(); \
    _nop_(); \
    _nop_(); \
    _nop_(); \
    _nop_(); // 宏定义

/*LCD屏幕的管脚*/
#define CLK P35
#define STB P13
#define DIO P14
#define BACKLIGHT P36
/**
 * @brief  LCD SPI发送8位数据，从低位开始
 * @note
 * @retval
 */
static void send_8bit(unsigned char dat)
{
    unsigned char data i;
    for (i = 0; i < 8; i++)
    {
        CLK = 0;
        if (dat & 0x01)
        {
            DIO = 1;
        }
        else
        {
            DIO = 0;
        }
        _nop_();
        _nop_();
        _nop_();
        CLK = 1;
        dat >>= 1;
    }
    CLK = 0;
    DIO = 0;
}

/**
 * @brief  LCD SPI 发送控制命令
 * @param  com : 命令字
 * @note
 * @retval
 */
static void send_command(unsigned char com)
{
    STB = 1; // STB置高
    nop;
    STB = 0;        // STB置低
    send_8bit(com); // 发送8bit数据
}

/**
 * @brief  LCD 下发显示数据
 * @param  dat  : 数据
 * @param  addr : 地址
 * @note
 * @retval
 */
static void display(unsigned char dat, unsigned char addr)
{
    // unsigned char i;
    send_command(0x00); // 设置显示模式，4位7段模式
    send_command(0x44); // 设置数据命令，采用固定地址模式
    send_command(addr); // 设置显示地址  red1:0xc0 red2:0xc2 green1:0xc4 green2:0xc6
    send_8bit(dat);     // 从00H开始，偶数地址送显示数据
                        //  send_8bit(0x00); //因为SEG9-14未用到，所以奇数地址送全0
    send_command(0x8f); // 设置显示命令，打开显示并设置占空比14/16.
    STB = 1;
}
/**
 * @brief  LCD 清屏
 * @note
 * @retval
 */
static void clear(void)
{
    display(ZERO[0], 0xc0);
    display(ZERO[0], 0xc2);
    display(ZERO[0], 0xc4);

    display(ZERO[0], 0xc6);
}
/**
 * @brief  LCD 打开背光
 * @note
 * @retval
 */
void bt_lcd_backlight_open(void)
{
    BACKLIGHT = 1;
}
/**
 * @brief  LCD 关闭背光
 * @note
 * @retval
 */
// void bt_lcd_backlight_close(void)
//{
//     BACKLIGHT = 0;
// }
/**
 * @brief  LCD 清屏
 * @note
 * @retval
 */
void bt_lcd_clear(void)
{
    clear();
}
// /**
//  * @brief  LCD 下发显示数据
//  * @param  disp  : 下发显示参数
//  * @note
//  * @retval
//  */
// void bt_lcd_display(bt_lcd_display_s *disp)
// {
//     static unsigned char data last_num = 0xfe;
//     static unsigned char data last_color = 0xfe;
//     unsigned char data ret1, ret2;

//     if (disp->is_blink == 1)
//     {
//         last_color = 0xfe;
//         last_num = 0xfe;
//     }
//     else
//     {
//         // 进行过滤
//         if (last_num == disp->num && last_color == disp->color)
//         {
//             return;
//         }
//         else
//         {
//             last_color = disp->color;
//             last_num = disp->num;
//         }
//     }
//     // 显示索引计算
//     if (disp->num == 0xff)
//     {
//         ret1 = 0xf; // 显示ff
//         ret2 = 0xf;
//     }
//     else
//     {
//         ret1 = disp->num % 10;        // 个位
//         ret2 = (disp->num / 10) % 10; // 十位
//     }

//     // 清屏
//     clear();

//     if (disp->dir == BT_LCD_DIR_UP) // 正向显示
//     {
//         if (disp->color == BT_LCD_RED) // 红色
//         {
//             display(Upright[ret1], 0xc2); // 显示个位
//             display(Upright[ret2], 0xc0); // 显示十位
//         }
//         else // 绿色
//         {
//             display(Upright[ret1], 0xc6); // 显示个位
//             display(Upright[ret2], 0xc4); // 显示十位
//         }
//     }
//     else // 反向显示
//     {
//         if (disp->color == BT_LCD_RED) // 红色
//         {
//             display(Reserve[ret1], 0xc0); // 显示个位
//             display(Reserve[ret2], 0xc2); // 显示十位
//         }
//         else // 绿色
//         {
//             display(Reserve[ret1], 0xc4); // 显示个位
//             display(Reserve[ret2], 0xc6); // 显示十位
//         }
//     }
// }

void bt_lcd_display(bt_lcd_display_s *disp)
{
    static unsigned char current_num = 0xee;
    static unsigned char current_color = 0xee;

    if (disp->num != current_num || disp->color != current_color)
    {
        current_num = disp->num;
        current_color = disp->color;
        clear();
        if (current_color == 0)
        {

            display(Upright[current_num & 0xf], 0xc2);        // 显示个位
            display(Upright[(current_num >> 4) & 0xf], 0xc0); // 显示十位
        }
        else
        {

            display(Upright[current_num & 0xf], 0xc6);        // 显示个位
            display(Upright[(current_num >> 4) & 0xf], 0xc4); // 显示十位
        }
    }
}

/**
 * @brief  LCD 初始化
 * @note
 * @retval
 */
void bt_lcd_init(void)
{
    GPIO_InitTypeDef xdata GPIO_InitStructure;        // 结构定义
                                                      // LCD
    GPIO_InitStructure.Pin = GPIO_Pin_3 | GPIO_Pin_4; // 指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
    GPIO_InitStructure.Mode = GPIO_OUT_PP;            // 指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P1, &GPIO_InitStructure);       // 初始化

    // LCD和背光
    GPIO_InitStructure.Pin = GPIO_Pin_5 | GPIO_Pin_6;
    GPIO_InitStructure.Mode = GPIO_OUT_PP;
    GPIO_Inilize(GPIO_P3, &GPIO_InitStructure);

    BACKLIGHT = 1;
}
